﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Controls;
using Utility;
using Model.Modules;
using System.Data.Entity;
using System.Windows;
using System.Windows.Threading;

using System.Timers;
using ViewModel.VM;
using Model;
using System.Xml.Linq;
using System.Collections.ObjectModel;
using System.Configuration;
using Google.Protobuf.WellKnownTypes;
using System.Data.Entity.Migrations;
using MySql.Data.MySqlClient;
using ViewModel.VM.Control;
using Newtonsoft.Json;
using System.Windows.Controls.Primitives;
using System.Management.Instrumentation;
using Newtonsoft.Json.Linq;
using Proxy;


namespace ViewModel
{
    public class VM_WindowMain : BaseViewModel
    {
        private static VM_WindowMain instance;
        public static VM_WindowMain GetInstance()
        {
            if (instance == null)
                instance = new VM_WindowMain();
            return instance;
        }

        public static surfacedetectEntities surfaceEntities;

        public string _HeaderName = "";
        public string HeaderName { get { return _HeaderName; } set { _HeaderName = value; OnPropertyChanged(); } }

        public Double temperarture ;
        public Double Temperarture { get { return temperarture; } set { temperarture = value; OnPropertyChanged(); } }


        public Page _DownLoadTaskPage;
        public Page DownLoadTaskPage { get { return _DownLoadTaskPage; } set { _DownLoadTaskPage = value; OnPropertyChanged(); } }
        public Page _FrameSource;
        public Page FrameSource { get { return _FrameSource; } set { _FrameSource = value; OnPropertyChanged(); } }

        public bool _isrunning = true;
        public bool Isrunning { get { return _isrunning; } set { _isrunning = value; OnPropertyChanged(); } }

        public DateTime timenow;
        public DateTime Timenow { get { return timenow; } set { timenow = value; OnPropertyChanged(); } }

        public TimeSpan onlinetime;
        public TimeSpan Onlinetime { get { return onlinetime; } set { onlinetime = value; OnPropertyChanged(); } }

        public double speed;
        public double Speed { get { return speed; } set { speed = value; OnPropertyChanged(); } }

        //兴橙使用CurrentSpeed，用户可以手动调整，其他项目用Speed
        public double CurrentSpeed { get { return currentspeed; } set { 
                currentspeed = value; 
                OnPropertyChanged(); 
            } }
        public double currentspeed;

        public string currentSteelType;
        public string CurrentSteelType { get { return currentSteelType; } set { 
                currentSteelType = value; 
                OnPropertyChanged();
                
            } }

        public ObservableCollection<gradeconfig> GradeConfigList { get; set; }
        public gradeconfig CurrentGradeConfig { get { return currentGradeConfig; }
            set { 
                currentGradeConfig = value; 
                OnPropertyChanged();
                applyCurrentGrade();
            } }
        private gradeconfig currentGradeConfig;

        public ObservableCollection<DefectFilterModel> DefectFilterList { get { return StaticData.DefectFilterList; } set { StaticData.DefectFilterList = value; OnPropertyChanged(); } }
        private ObservableCollection<DefectFilterModel> defectFilterList;
        public DefectFilterModel CurrentDefectFilter
        {
            get { return StaticData.CurrentDefectFilter; }
            set
            {
                StaticData.CurrentDefectFilter = value;
                OnPropertyChanged();
                UpdateViewCommand_Executed(null);

            }
        }
        private DefectFilterModel currentDefectFilter;

        public new ObservableCollection<defect_type> DefectTypes { get; set; } 
        //public bool isRefreshing;

        //通过StaticData.IsRefreshing控制客户端各个Page是否自动刷新图片数据
        public bool WindowIsRefreshing{ 
            get { return IsRefreshing; }
            set { IsRefreshing = value;setFereshStatus(); }
        }
        private bool isMinimized;
        public bool IsMinimized
        {
            get { return isMinimized; }
            set {isMinimized = value;setFereshStatus();}
        }

        public void setFereshStatus() {
            if (WindowIsRefreshing&&!IsMinimized)
            {
                //StaticData.IsRefreshing = true;
                pageMain.LiveIsRefreshing = true;
                if (pageImageView != null)
                    pageImageView.StartRefreshing();
                Console.WriteLine("start refresh");
               
            }
            else
            {
                //StaticData.IsRefreshing = false;
                pageMain.LiveIsRefreshing = false;
                if (pageImageView != null)
                    pageImageView.StopRefreshing();
                Console.WriteLine("stop refresh");
            }
        }
        public bool HistoryChecked { get; set; }
        public bool ReviewChecked { get; set; }
        
        public DateTime StartTime { get; set; }

        VM_PageMain pageMain = null;
        VM_PageHistory pageHistory = null;
        VM_PageAnalysis pageHistoryAlerm = null;
        VM_PageImageView pageImageView = null;
        VM_PageMonitor pageMonitor = null;
        VM_PageReviewDefect pageReview=null;
        DefectDataHelper defectDataHelper;
        SignalRClient signalRClient;

        //通过getinstance获取实例(单例)
        private VM_WindowMain()
        {
            //instance = this;
            WindowMain =this.UIElement as Window;
            Logger.Info("开始初始化");
            initStaticData();
            Speed = 10;
            defectDataHelper = new DefectDataHelper();
            DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
            if (DefectFilterList.Any())
                CurrentDefectFilter = DefectFilterList.FirstOrDefault();
            else
                CurrentDefectFilter = null;

            pageMonitor = new VM_PageMonitor();
            pageMain = new VM_PageMain();
            pageHistory = new VM_PageHistory();
            FrameSource = pageMain.UIElement as Page;
            VM_PageDownloadTask downloadTask=new VM_PageDownloadTask();
            DownLoadTaskPage = downloadTask.UIElement as Page;

            WindowIsRefreshing = true;
            StartTime = DateTime.Now;
            var timer = new Timer();
            timer.Interval = 1000;
            timer.Elapsed += new ElapsedEventHandler((s,e)=> {
                if(!IsMinimized&& System.Windows.Application.Current!=null)
                    System.Windows.Application.Current.Dispatcher.BeginInvoke(new Action(() =>
                    {
                        Timenow = DateTime.Now;
                        Onlinetime = DateTime.Now - StartTime;
                        Temperarture = StaticData.Temperature;
                        Speed = StaticData.Speed;
                    }));
            });
            timer.Start();

            (this.UIElement as Window).StateChanged += (s,e) => {
                if ((s as Window).WindowState == WindowState.Minimized)
                    IsMinimized = true;
                else
                    IsMinimized = false;
            };

            CloseCallBack = (s, e) =>
            {
                AlertSeriesHelper.sendData("21");
                AlertSeriesHelper.CloseDevice();
                signalRClient.Stop();
                pageMain.SaveAlertInfos();
                //pageMain.CloseConnection();
            };
            signalRClient = new SignalRClient("SteelDetection", "MyHub", $"http://{ConfigurationManager.AppSettings["wssaddress"]}:8093");
            signalRClient.OnMessageReceived += (msgtype, message) =>
            {
                try
                {
                    //Logger.Debug(msgtype);
                    //Logger.Debug(message);
                    switch (msgtype)
                    {
                        case "leftedge":
                            pageMain.CurrentLeftEdge = (int)JObject.Parse(message)["leftedge"];
                            break;
                        case "devicestatus":
                            var devicestatus = JsonConvert.DeserializeObject<devicestatus>(message);
                            var device=pageMonitor.DeviceStatuslist.Where(t => t.devicename == devicestatus.devicename).FirstOrDefault();
                            if (device != null)
                            {
                                device.temperature = devicestatus.temperature;
                                device.connection = devicestatus.connection;
                            }
                            StaticData.Temperature = pageMonitor.DeviceStatuslist.Where(d=>int.Parse(d.devicename)<=7).Average(t => t.temperature);
                            break;
                        case "alertinfo":
                            var alertinfo = JsonConvert.DeserializeObject<AlertInfo>(message);
                            DoMenthodByDispatcher(() =>
                            {
                                pageMain?.AlertInfos.Insert(0, alertinfo);
                            });
                            break;
                    }
                }
                catch (Exception ex)
                {
                    Logger.Error(ex.Message, ex);
                }
            };
            signalRClient.OnStatusChanged += (isconnected) =>
            {
                if (pageMonitor != null)
                    pageMonitor.ServiceInfolist.Where(t => t.Name == "控制服务").FirstOrDefault().Status = isconnected;
            };
            _ = signalRClient.Start();
        }
        private void initStaticData() {
            surfaceEntities = new surfacedetectEntities();
            if (!surfaceEntities.Database.Exists())
            {
                MessageBox("数据库连接失败");
                Logger.Info("数据库连接失败");
                this.Close();
            }
            StaticData.ShownMode = ShownMode.Icon;
            initDefectTypes();
            initSysConfig();
            //获取所有单位
            StaticData.UnitList = new ObservableCollection<unit>(surfaceEntities.unit.ToList());
        }

        private void initSysConfig()
        {
            //Diff 兴橙需要CurrentSpeed，其他项目不用，不初始化
            try
            {
                StaticData.SysconfigList = new ObservableCollection<sysconfig>(surfaceEntities.sysconfig);
                CurrentSpeed = double.Parse(surfaceEntities.sysconfig.Where(t => t.key == "speed").FirstOrDefault().value);
                CurrentSteelType = surfaceEntities.sysconfig.Where(t => t.key == "steeltype").FirstOrDefault().value;
            }
            catch (Exception ex)
            {
                Logger.Error(ex.Message, ex);
            }
            try
            {
                var xdoc = XDocument.Load(Environment.CurrentDirectory + "\\SysConfig.xml");
                var surfacelist = xdoc.Root.Element("surfacelist");
                foreach (var surface in surfacelist.Elements())
                {
                    StaticData.SurfaceList.Add(new Surface()
                    {
                        id = int.Parse(surface.Attribute("id").Value),
                        name = surface.Attribute("name").Value,
                        Cameras=new ObservableCollection<int>(surface.Attribute("cameras").Value.Split(',').Select(c=>int.Parse(c)))
                    });
                }
                StaticData.CameraList=new ObservableCollection<camera>(surfaceEntities.camera);
                var imagetyplist = xdoc.Root.Element("imagetypes");
                foreach (var imagetype in imagetyplist.Elements())
                {
                    StaticData.ImageTypeList.Add(new ImageType()
                    {
                        id = int.Parse(imagetype.Attribute("id").Value),
                        name = imagetype.Attribute("name").Value,
                    });
                }

                //初始化所有es数据表名称
                SysConfig.GetInstance().GetAttributeValue("sysconfig/establelist", "value");
                ESDataHelper.image_tablename = SysConfig.GetInstance().GetAttributeValue("sysconfig/establelist/image", "value");
                ESDataHelper.steel_defect_tablename = SysConfig.GetInstance().GetAttributeValue("sysconfig/establelist/steel_defect", "value");
                ESDataHelper.image_defect_tablename = SysConfig.GetInstance().GetAttributeValue("sysconfig/establelist/image_defect", "value");
                ESDataHelper.repeat_defect_tablename = SysConfig.GetInstance().GetAttributeValue("sysconfig/establelist/repeat_defect", "value");

            }
            catch (Exception ex)
            {
                return;
            }
            
            UpdateGradeCofig();

        }

        public BaseCommand ChangeMainFrameCommand{get=> new BaseCommand(ChangeMainFrameCommand_Executed);}


        public void ChangeMainFrameCommand_Executed(object obj)
        {
            
            string pageName = obj.ToString();
            switch(pageName)
            {
                case "online":
                    if(pageMain==null)
                        pageMain = new VM_PageMain();
                    FrameSource = pageMain.UIElement as Page;
                    StaticData.ActivePage = PageName.PageMain;

                    break;
                case "history":
                    if (pageHistory == null)
                        pageHistory = new VM_PageHistory();
                    FrameSource = pageHistory.UIElement as Page;
                    StaticData.ActivePage = PageName.PageHistory;

                    break;
                case "analysis":
                    if (pageHistoryAlerm == null)
                        pageHistoryAlerm = new VM_PageAnalysis();
                    FrameSource = pageHistoryAlerm.UIElement as Page;
                    StaticData.ActivePage = PageName.PageAnalysis;
                    break;
                case "imageview":
                    if (pageImageView == null)
                        pageImageView = new VM_PageImageView();
                    FrameSource = pageImageView.UIElement as Page;
                    StaticData.ActivePage = PageName.PageImageView;
                    break;
                case "review":
                    if (pageReview == null)
                        pageReview = new VM_PageReviewDefect();
                    FrameSource = pageReview.UIElement as Page;
                    StaticData.ActivePage = PageName.PageReview;
                    break;
                case "monitor":
                    if (pageMonitor == null)
                        pageMonitor = new VM_PageMonitor();
                    FrameSource = pageMonitor.UIElement as Page;
                    StaticData.ActivePage = PageName.PageMonitor;
                    break;

            }
            HistoryChecked = StaticData.ActivePage == PageName.PageHistory;

        }

        public BaseCommand RefreshCommand { get => new BaseCommand(RefreshCommand_Executed); }
        public void RefreshCommand_Executed(object obj)
        {
            if (pageMain == null)
                return;
            string action = obj.ToString();
            switch (action)
            {
                case "stop":
                    WindowIsRefreshing = false;
                    break;
                case "running":
                    WindowIsRefreshing = true;
                    break;
            }
        }

        public BaseCommand UpdateViewCommand { get => new BaseCommand(UpdateViewCommand_Executed); }
        public void UpdateViewCommand_Executed(object obj)
        {
            if (CurrentDefectFilter != null)
            {
                pageMain?.FilterView();
                pageHistory?.FilterView();
            }
        }

        //Diff 兴橙需要更新CurrentSpeed，其他项目不用
        public BaseCommand ConfirmSpeedCommand { get => new BaseCommand((obj) => {
            updateSysInfoRecord("speed", CurrentSpeed.ToString());
            updateSysInfoRecord("steeltype", CurrentSteelType.ToString());
        }); }

        public BaseCommand CloseWindowCommand { get => new BaseCommand(CloseWindowCommand_Executed); }

        private void CloseWindowCommand_Executed(object obj)
        {
            if(pageReview!=null)
            {
                //pageReview.SaveDefect();
            }
            this.Close();
        }

        public BaseCommand MinWindowCommand { get => new BaseCommand(MinWindowCommand_Executed); }

        private void MinWindowCommand_Executed(object obj)
        {
            
            (this.UIElement as Window).WindowState = WindowState.Minimized;

        }

        public BaseCommand MaxWindowCommand { get => new BaseCommand(MaxWindowCommand_Executed); }

        private void MaxWindowCommand_Executed(object obj)
        {
            var maxbutton = this.UIElement.FindName("MaxButton") as Button;
            if (obj.ToString() == "normal")
            {
                (this.UIElement as Window).MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
                (this.UIElement as Window).WindowState = WindowState.Maximized;
                maxbutton.CommandParameter = "max";
                maxbutton.SetResourceReference(Button.StyleProperty, "RestoreButtonStyle");

            }
            else if (obj.ToString() == "max")
            {
                (this.UIElement as Window).WindowState = WindowState.Normal;
                maxbutton.CommandParameter = "normal";
                maxbutton.SetResourceReference(Button.StyleProperty, "MaxButtonStyle");
            }

            
        }

        private void initDefectTypes() {

            
            try
            {
                //获取所有缺陷类型
                StaticData.AllDefectTypes = new ObservableCollection<defect_type>(surfaceEntities.defect_type.ToList());
                //获取所有缺陷类型
                StaticData.DefectTypes = new ObservableCollection<defect_type>(surfaceEntities.defect_type.Where(t=>t.isdetectout==true).ToList());
                DefectTypes= StaticData.DefectTypes;
                //获取数据库第一个套餐作为当前套餐
                var defectfilterlist = surfaceEntities.defect_filter.ToList();
                var DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(defectfilterlist);
                if (!DefectFilterList.Any())
                {
                    var defect_filter = SteelDefectFilterHelper.buildFilteredEntity(SteelDefectFilterHelper.GenerateNewFilter());

                    surfaceEntities.defect_filter.Add(defect_filter);
                    if (surfaceEntities.SaveChanges() != 1)
                    {
                        MessageBox("保存失败");
                        Logger.Info($"添加自定义套餐：{defect_filter.name}失败");
                    }
                    DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
                }
                StaticData.DefectFilterList= DefectFilterList;
                StaticData.CurrentDefectFilter = StaticData.DefectFilterList.FirstOrDefault();
            }
            catch (Exception ex)
            {

                Logger.Error(ex.Message,ex);
                this.Close();
            }
        }


        private bool updateSysInfoRecord(string key, string value)
        {
            var config=surfaceEntities.sysconfig.Where(t => t.key == key).FirstOrDefault();
            if (config != null)
            {
                config.value = value;
                surfaceEntities.sysconfig.AddOrUpdate(config);
                surfaceEntities.SaveChanges();
            }

            return true;
        }

        public void GotoHistoryDefect(string main_id, string steeldefect_id)
        {
            pageHistory?.GotoHistoryDefect(main_id, steeldefect_id);
        }
        public void GotoReviewDefect(string main_id)
        {
            if(pageReview == null)
                pageReview = new VM_PageReviewDefect();
            pageReview?.GotoReviewDefect(main_id);
            FrameSource = pageReview.UIElement as Page;
            StaticData.ActivePage = PageName.PageReview;
            ReviewChecked = true;
        }



        /// <summary>
        /// 添加过滤器
        /// </summary>
        public BaseCommand AddFilterCMD
        {
            get => new BaseCommand((obj) =>
            {

                var dlg = new VM_WindowTextBoxDlg("请输入新套餐名称");
                dlg.ShowDialog();
                if ((dlg.UIElement as Window).DialogResult != true)
                    return;
                if (DefectFilterList.Select(s => s.name).Contains(dlg.Text))
                {
                    MessageBox("套餐列表中已经存在该名称，添加失败");
                    return;
                }
                var defect_filter = SteelDefectFilterHelper.buildFilteredEntity(SteelDefectFilterHelper.GenerateNewFilter(dlg.Text));
                surfaceEntities.defect_filter.Add(defect_filter);
                if (surfaceEntities.SaveChanges() != 1)
                {
                    MessageBox("保存失败");
                    Logger.Info($"添加自定义套餐：{defect_filter.name}失败");
                }
                DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
                CurrentDefectFilter = DefectFilterList.Where(t => t.name == defect_filter.name).First();

            });
        }

        public BaseCommand RemoveFilterCMD
        {
            get => new BaseCommand((obj) =>
            {
                var index = DefectFilterList.IndexOf(CurrentDefectFilter);
                if (index <= 0)
                {
                    MessageBox("默认套餐无法删除,请选择其他自定义套餐");
                    return;
                }

                MessageBox("删除确认", $"请确认是否删除名称为{CurrentDefectFilter.name}的缺陷套餐？", new Action<bool>((confirm) =>
                {
                    if (confirm)
                    {
                        var deletedfilter = surfaceEntities.defect_filter.Where(t => t.id == CurrentDefectFilter.id).First();
                        surfaceEntities.defect_filter.Remove(deletedfilter);
                        if (surfaceEntities.SaveChanges() < 1)
                        {
                            MessageBox("删除失败");
                            Logger.Info($"删除自定义套餐：{CurrentDefectFilter.name}失败");
                        }
                        DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
                        CurrentDefectFilter = DefectFilterList[index - 1];
                    }
                }));
            });
        }

        /// <summary>
        /// 修改过滤器名称
        /// </summary>
        public BaseCommand ModifyFilterNameCMD
        {
            get => new BaseCommand((obj) =>
            {

                var dlg = new VM_WindowTextBoxDlg("请修改名称", CurrentDefectFilter.name);
                dlg.ShowDialog();
                if ((dlg.UIElement as Window).DialogResult != true)
                    return;
                if (DefectFilterList.Select(s => s.name).Contains(dlg.Text))
                {
                    MessageBox("套餐列表中已经存在该名称或未修改缺陷名称，修改失败");
                    return;
                }
                CurrentDefectFilter.name = dlg.Text;
                var defect_filter = SteelDefectFilterHelper.buildFilteredEntity(CurrentDefectFilter);
                surfaceEntities.defect_filter.AddOrUpdate(defect_filter);
                if (surfaceEntities.SaveChanges() != 1)
                {
                    MessageBox("保存失败");
                    Logger.Info($"修改自定义套餐：{defect_filter.name}失败");
                }
                DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
                CurrentDefectFilter = DefectFilterList.Where(t => t.name == defect_filter.name).First();
                MySqlConnectionStringBuilder scsb = new MySqlConnectionStringBuilder();


            });
        }



        /// <summary>
        /// 保存过滤器内容修改
        /// </summary>
        public BaseCommand SaveFilterCMD
        {
            get => new BaseCommand((obj) =>
            {
                var currentFilterEntity = SteelDefectFilterHelper.buildFilteredEntity(CurrentDefectFilter);
                surfaceEntities.defect_filter.AddOrUpdate(currentFilterEntity);
                surfaceEntities.SaveChanges();
                MessageBox("保存成功");
            });
        }


        /// <summary>
        /// 还原过滤器修改
        /// </summary>
        public BaseCommand ResetFilterCMD
        {
            get => new BaseCommand((obj) =>
            {
                string fitlername = CurrentDefectFilter.name;
                DefectFilterList = SteelDefectFilterHelper.ConvertFilterRecordsToModels(surfaceEntities.defect_filter.ToList());
                CurrentDefectFilter = DefectFilterList.Where(t => t.name == fitlername).First();
            });
        }

        public BaseCommand SelectAllFilterCMD
        {
            get => new BaseCommand((isselectall) =>
            {
                CurrentDefectFilter.DefectTpyeFilterInfos.All(typeinfo =>
                {
                    typeinfo.isFiltered = (bool)isselectall;
                    return true;
                });
                UpdateViewCommand_Executed(null);
            });
        }


        private void applyCurrentGrade()
        {
            if (CurrentGradeConfig == null)
                return;
            var config = surfaceEntities.sysconfig.Where(t => t.key == "gradeconfigid").AsNoTracking().FirstOrDefault();
            config.value = CurrentGradeConfig.id.ToString();
            surfaceEntities.sysconfig.AddOrUpdate(config);
            surfaceEntities.SaveChanges();
        }
        public void UpdateGradeCofig()
        {
            GradeConfigList=new ObservableCollection<gradeconfig>(surfaceEntities.gradeconfig.AsNoTracking());
            var gradeconfigid= surfaceEntities.sysconfig.Where(t => t.key == "gradeconfigid").AsNoTracking().FirstOrDefault().value;
            
            CurrentGradeConfig = GradeConfigList.Where(t => t.id.ToString() == gradeconfigid).FirstOrDefault();
        }

    }
}
